#include "clientsocket.h"
#include "client.h"

ClientSocket::ClientSocket(QTcpSocket *socket, Client *client)
{
    deleteLaterExecuted = false;
    m_isReadingData     = false;
    m_socket            = socket;
    m_client            = client;
    dataSize            = 0;

    connect( m_socket, SIGNAL(readyRead()), this, SLOT(readSocket()) );
}

ClientSocket::~ClientSocket()
{
    if( m_socket )
        m_socket->deleteLater();
}

void ClientSocket::deleteLater()
{
    if( m_isReadingData )
    {
        deleteLaterExecuted = true;

        disconnect( this, 0, m_client, 0 );
        disconnect( m_socket, 0, m_client, 0 );
    }
    else
    {
        delete this;
    }
}

void ClientSocket::readSocket()
{
    QDataStream in(m_socket);
    in.setVersion(QDataStream::Qt_4_0);

    m_isReadingData = true;

    while( !deleteLaterExecuted && m_socket->bytesAvailable() )
    {
        if( dataSize == 0 )
        {
            if( m_socket->bytesAvailable() < (int)sizeof(quint16) )
                return;

            in >> dataSize;
        }

        if( m_socket->bytesAvailable() < dataSize )
            return;

        // Read package
        Package package;
        if( fillPackage(&package, &in) )
        {
            emit newPackage(&package);
        }
        else
            printf("Got an either unhandled or not acceptable package from Client %d!\n", m_client->getId());

        dataSize = 0;
    }

    m_isReadingData = false;

    if( deleteLaterExecuted )
        deleteLater();
}

bool ClientSocket::fillPackage(Package *package, QDataStream *incommingStream)
{
    // Get packagetyp
    *incommingStream >> package->typ;

    if( package->typ == TUNNEL_PACKAGETYP_MESSAGE )
    {
        *incommingStream >> package->to;
        *incommingStream >> package->message;
        package->from = m_client->getName();

        // To send messages the client has to be connected and authentificated.
        if( m_client->getStatus() != connected )
            return false;

        return true;
    }
    else if( package->typ == TUNNEL_PACKAGETYP_SYSTEM )
    {
        *incommingStream >> package->commandCategory;
        *incommingStream >> package->command;
        *incommingStream >> package->arguments;

        return true;
    }
    else
        printf("Error: Unhandled packagetyp!: %d\n", package->typ);

    return false;
}

void ClientSocket::sendPackage(Package *package)
{
    if( !package )
        return;

    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);

    out << (quint16)0;
    out << package->typ;

    if( package->typ == TUNNEL_PACKAGETYP_SYSTEM )
    {
        out << package->commandCategory;
        out << package->command;
        out << package->arguments;
    }
    else if( package->typ == TUNNEL_PACKAGETYP_MESSAGE )
    {
        // To receive messages the client has to be connected and authentificated.
        if( m_client->getStatus() != connected )
            return;

        out << package->to;
        out << package->message;
        out << package->from;
    }
    else
    {
        printf("Tryed to send invalid package from typ: %d\n", package->typ);

        return;
    }

    // Send package
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));

    m_socket->write(block);
}
